﻿using System;
using System.Net;
using System.Threading.Tasks;
using eLibrary;

namespace Letter.Net;

public abstract class AHost<TTransportOptions, TFeatureOptions> : IHost<TTransportOptions, TFeatureOptions>
    where TTransportOptions : class, ITransportOptions, new()
    where TFeatureOptions : class, IFeatureOptions, new()
{
    public AHost(string name)
    {
        this.Id = StringIdGenerator.GetNextId();
        this.Name = name;
    }
    
    protected TTransportOptions transportOptions;
    protected TFeatureOptions featureOptions;
    private Func<AConnection> connectionFunc;

    public string Id { get; }
    public string Name { get; }
    public abstract EndPoint BindEndPoint { get; }

    public void ConfigureChannelOptions(TTransportOptions channelOptions) => this.transportOptions = channelOptions;
    public void ConfigureFeatureOptions(TFeatureOptions featureOptions) => this.featureOptions = featureOptions;
    public void ConfigureConnection(Func<AConnection> func) => this.connectionFunc = func;

    public virtual void Build()
    {
        if (this.transportOptions == null)
        {
            this.transportOptions = new TTransportOptions();
        }

        if (this.featureOptions == null)
        {
            this.featureOptions = new TFeatureOptions();
        }
        
        if (this.connectionFunc == null)
        {
            throw new Exception("Connection need to be configured");
        }
    }

    protected AConnection CreateConnection()
    {
        var connection = this.connectionFunc.Invoke();
        if (connection == null)
        {
            throw new Exception("The connection created is empty");
        }

        return connection;
    }

    public virtual Task BindAsync(EndPoint endPoint)
    {
        throw new NotImplementedException();
    }

    public virtual Task ConnectAsync(EndPoint endPoint)
    {
        throw new NotImplementedException();
    }

    public abstract Task StopAsync();
}